package com.study.frame;

import com.study.entity.Bullet;
import com.study.entity.Direction;
import com.study.entity.Explode;
import com.study.entity.Tank;
import com.study.manager.ResourceManager;
import com.study.utils.ApplicationComponent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * 游戏展示窗口
 * 使用 @Lazy 保证 ApplicationEnvironment 先进行创建, 防止空指针
 * @Author ZhuHJay
 * @Date 2021/9/13 22:53
 */
@Lazy
@Component
public class TankWarFrame extends Frame{

    public static final int FRAME_WIDTH;
    public static final int FRAME_HEIGHT;
    /** 敌机 **/
    private List<Tank> tankList = new ArrayList<>();
    /** 坦克发射的子弹 **/
    private List<Bullet> bullets = new ArrayList<>();
    /** 爆炸的画面展示 **/
    private List<Explode> explodes = new ArrayList<>();

    static {
        // 获取配置文件中的关于界面的大小配置
        // TODO 后续可以对窗口的设置大小进行判断, 如果超出了范围就...
        String width = ApplicationComponent.getProperty("frame.width", "1280");
        String height = ApplicationComponent.getProperty("frame.height", "760");
        FRAME_WIDTH = Integer.parseInt(width);
        FRAME_HEIGHT = Integer.parseInt(height);
    }

    @Autowired
    private Tank myTank;

    public TankWarFrame(){
        setSize(FRAME_WIDTH, FRAME_HEIGHT);
        setTitle("Tank War");
        setResizable(false);
        setLocationRelativeTo(null);

        // 窗口事件设置 -> 窗口关闭事件
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        // 添加键盘监听事件
        addKeyListener(new CustomKeyListener());

        // 添加敌机坦克
        Random random = new Random();
        for (int i = 0; i < 5; i++) {
            Tank tank = new Tank(
                    random.nextInt(FRAME_WIDTH - Tank.TANK_WIDTH),
                    random.nextInt(FRAME_HEIGHT - Tank.TANK_HEIGHT),
                    false );
            tank.setImage(ResourceManager.tankUP);
            tank.setMoving(true);
            tankList.add(tank);
        }
    }

    /** 使用双缓冲解决闪烁的问题 **/
    private Image offScreenImage = null;
    @Override
    public void update(Graphics g) {
        if(offScreenImage == null) {
            offScreenImage = this.createImage(FRAME_WIDTH,FRAME_HEIGHT);
        }
        Graphics gOffScreen = offScreenImage.getGraphics();
        Color c = gOffScreen.getColor();
        gOffScreen.setColor(Color.BLACK);
        gOffScreen.fillRect(0, 0, FRAME_WIDTH,FRAME_HEIGHT);
        gOffScreen.setColor(c);
        paint(gOffScreen);
        g.drawImage(offScreenImage, 0, 0, null);
    }

    @Override
    public void paint(Graphics graphics){
        // 需要调用父类来进行画面的清除, 否则会有上一次的残留
        super.paint(graphics);
        // 信息面板的绘制
        paintPanel(graphics);
        // 游戏界面绘制
        paintGamePanel(graphics);
        // 游戏碰撞测试
        gameBumpWith();
    }

    /** 游戏碰撞检测 **/
    private void gameBumpWith() {
        // 进行坦克间的碰撞判断
        for (int i = 0; i < tankList.size(); i++) {
            // 碰撞测试
            myTank.bumpWith(tankList.get(i));
        }
        // 进行子弹的碰撞判断
        for (int i = 0; i < bullets.size(); i++) {
            for (int i1 = 0; i1 < tankList.size(); i1++) {
                bullets.get(i).bumpWith(tankList.get(i1));
            }
        }
    }

    /** 绘制游戏物体 **/
    private void paintGamePanel(Graphics graphics) {
        // 绘制坦克
        myTank.paint(graphics);
        // 绘制敌方坦克
        for (int i = 0; i < tankList.size() ; i++) {
            tankList.get(i).paint(graphics);
        }
        // 绘制子弹
        for (int i = 0; i < bullets.size(); i++) {
            bullets.get(i).paint(graphics);
        }
        // 绘制爆炸画面
        for (int i = 0; i < explodes.size(); i++) {
            explodes.get(i).paint(graphics);
        }
    }

    /** 文字面板的绘制 **/
    private void paintPanel(Graphics graphics) {
        // 子弹数量显示, 以及敌机坦克
        graphics.drawString("当前子弹的数量: " + bullets.size(), 30, 45);
        graphics.drawString("当前地方坦克的数量: " + tankList.size(), 30, 60);
    }

    /** 内部类: 键盘监听事件 **/
    private class CustomKeyListener extends KeyAdapter{
        // 用来存储当前的运动方向
        boolean isLeft = false;
        boolean isUp = false;
        boolean isRight = false;
        boolean isDown = false;

        /** 键盘按下事件 **/
        @Override
        public void keyPressed(KeyEvent e) {
            switch ( e.getKeyCode() ){
                case KeyEvent.VK_LEFT:
                    isLeft = true;
                    break;

                case KeyEvent.VK_UP:
                    isUp = true;
                    break;

                case KeyEvent.VK_RIGHT:
                    isRight = true;
                    break;

                case KeyEvent.VK_DOWN:
                    isDown = true;
                    break;

                default:
                    break;
            }
            setTankData();
        }

        /** 键盘弹起的事件 **/
        @Override
        public void keyReleased(KeyEvent e) {
            switch ( e.getKeyCode() ){
                case KeyEvent.VK_LEFT:
                    isLeft = false;
                    break;

                case KeyEvent.VK_UP:
                    isUp = false;
                    break;

                case KeyEvent.VK_RIGHT:
                    isRight = false;
                    break;

                case KeyEvent.VK_DOWN:
                    isDown = false;
                    break;

                case KeyEvent.VK_CONTROL:
                    myTank.fire();
                    break;

                default:
                    break;
            }
            setTankData();
        }

        /** 修改主体中的数据(运动物体) **/
        private void setTankData(){
            // 如果此时任何按键的状态为 true , 那么就是处于运动状态
            if( isLeft || isUp || isRight || isDown ){
                myTank.setMoving(true);
                // 进行状态的修改
                if( isDown ) {
                    myTank.setDirection(Direction.DOWN);
                    myTank.setImage(ResourceManager.myTankDOWN);
                }
                if( isRight ) {
                    myTank.setDirection(Direction.RIGHT);
                    myTank.setImage(ResourceManager.myTankRIGHT);
                }
                if( isUp ) {
                    myTank.setDirection(Direction.UP);
                    myTank.setImage(ResourceManager.myTankUP);
                }
                if( isLeft ) {
                    myTank.setDirection(Direction.LEFT);
                    myTank.setImage(ResourceManager.myTankLEFT);
                }
            }else{
                myTank.setMoving(false);
            }
        }
    }

    /** 向子弹的容器中添加子弹 **/
    public void addBullet(Bullet bullet){
        bullets.add(bullet);
    }

    /** 向子弹的容器中移除子弹 **/
    public void removeBullet(Bullet bullet){
        bullets.remove(bullet);
    }

    /** 向爆炸的容器中添加爆炸的场景 **/
    public void addExplode(Explode explode){
        explodes.add(explode);
    }

    /** 从坦克的容器中移除坦克 **/
    public void removeTank(Tank tank){
        tankList.remove(tank);
    }

    /** 从爆炸容器中移除爆炸 **/
    public void removeExplode(Explode explode) {
        explodes.remove(explode);
    }

}
